package com.witframework.web.filter;

import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;

/** 自动处理<code>multipart/form-data</code> requests(file uploads)文件上传
 * 该类改编自<code>com.oreilly.servlet.MultipartFilter</code>
 * 增加了在上传时可以指定上传子目录,指定最大上传文件大小,指定编码方式
 * 也可指定重命名策略(类文件名classname),否则使用缺省的oreilly命名策略
 * <code>com.oreilly.servlet.multipart.DefaultFileRenamePolicy</code>
 * 并且这些设置可以在单个的上传中重新设置以覆盖预指定的设定.
 * The filter capability requires Servlet API 2.3.
 * <p>
 * 
 * @author wuxinyang3000@hotmail.com
 * @version $Revision 1.0
 * @pdOid f28086fb-cc19-4345-82fc-e395a38ea406
 * @date 2004-11-11
 * @time 13:48:56 */
public class MultipartEncodingFilter implements Filter {
   /** @pdOid eb41b483-95a2-4cdd-a34d-483ad322f4b9 */
   private FilterConfig config = null;
   /** 缺省上传目录
    * 
    * @pdOid 01ee0dd0-afbd-4d53-b1d5-1b1bf1f413de */
   private String UPLOAD_DIR = null;
   private int MAXPOSTSIZE=5*1024 * 1024;
   private String ENCODING="GB2312";
   /** 是否允许覆盖初始化值
    * 
    * @pdOid 7137e8e8-cc27-4cf1-a330-d67f25ad1346 */
   private boolean reset = true;
   
   /** @param request
    * @pdOid b8fbae9d-17ad-4335-bf55-6671839b371e */
   private void initParameters(HttpServletRequest request) {
     if (request.getQueryString() != null) {
       Enumeration queryParameterNames = request.getParameterNames();
       while (queryParameterNames.hasMoreElements()) {
         Object paramName = queryParameterNames.nextElement();
         String[] values = request.getParameterValues( (String) paramName);
         Vector newValues = new Vector();
         for (int i = 0; i < values.length; i++) {
           newValues.add(values[i]);
         }
         parameters.put(paramName, newValues);
       }
     }
   }
   
   /**  name - Vector of values
    * 
    * @pdOid 8a47c964-fc17-478c-949c-6a5d4536fb69 */
   protected Hashtable parameters = new Hashtable();
   
   
   public void init(FilterConfig config) throws ServletException {
     this.config = config;
     File tempdir = (File) config.getServletContext().getAttribute("javax.servlet.context.tempdir");
     if (tempdir != null) {
       UPLOAD_DIR = tempdir.toString();
       //根据filter的设置
       if(config.getInitParameter("uploadDir")!=null&&!config.getInitParameter("uploadDir").equals("javax.servlet.context.tempdir"));{
    	   UPLOAD_DIR=config.getInitParameter("uploadDir");
       }
       if(StringUtils.isNotEmpty(config.getInitParameter("maxFileSize"))){
    	   MAXPOSTSIZE=Integer.parseInt(config.getInitParameter("maxFileSize"))*1024*1024;
       }
       if(StringUtils.isNotEmpty(config.getInitParameter("encoding"))){
    	   ENCODING=config.getInitParameter("encoding");
       }
     }
     else {
       throw new ServletException(
           "MultipartFilter: No upload directory found: set an uploadDir " +
           "init parameter or ensure the javax.servlet.context.tempdir " +
           "directory is valid");
     }
   }
   
   /** @pdOid 3c4c239d-59a1-4a00-840a-8c397914f5ad */
   public void destroy() {
     config = null;
   }
   
   /** @param request 
    * @param response 
    * @param chain
    * @exception IOException
    * @exception ServletException
    * @pdOid be1e15e6-8e2c-43d3-998b-6a2b801ab69e */
   public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException                      {
     HttpServletRequest req = (HttpServletRequest) request;
     String type = req.getHeader("Content-Type");
     // If this is not a multipart/form-data request continue
     if (type == null || !type.startsWith("multipart/form-data")) {
       chain.doFilter(request, response);
     }
     else {
       String dir = UPLOAD_DIR;
       int maxPostSize = MAXPOSTSIZE; //default is 5 Meg
       String encoding = ENCODING; //缺省编码;
      
       //如果允许页面覆盖原始设定,重新设定上传文件设置。
       if (reset) {
         initParameters(req);
         //上传目录
         if (getParameter("uploadDir") != null) {
           dir = getParameter("uploadDir");
         }
         //上传子目录
         if (getParameter("uploadSubDir") != null) {
           dir = dir + File.separator + getParameter("uploadSubDir");
         }
         //文件最大允许上传大小
         if (getParameter("maxFileSize") != null) {
           try {
             maxPostSize = Integer.parseInt(getParameter("maxFileSize")) * 1024 *
                 1024;
           }
           catch (NumberFormatException ex) {
             //no statement
           }
         }
       }
       File tempFile = new File(dir);
       if (!tempFile.exists()) {
         tempFile.mkdir();
       }
       MultipartWrapper multi = new MultipartWrapper(req, dir, maxPostSize,encoding);
       chain.doFilter(multi, response);
     }
   }
   
   /** @param name
    * @pdOid c3ce66b0-1e98-47fb-a133-7d88c13ecfa5 */
   public String getParameter(String name) {
     try {
       Vector values = (Vector) parameters.get(name);
       if (values == null || values.size() == 0) {
         return null;
       }
       String value = (String) values.elementAt(values.size() - 1);
       return value;
     }
     catch (Exception e) {
       return null;
     }
   }
   
   /** @param name
    * @pdOid 88c76916-0401-498e-bf56-85e27230ec99 */
   public String[] getParameterValues(String name) {
     try {
       Vector values = (Vector) parameters.get(name);
       if (values == null || values.size() == 0) {
         return null;
       }
       String[] valuesArray = new String[values.size()];
       values.copyInto(valuesArray);
       return valuesArray;
     }
     catch (Exception e) {
       return null;
     }
   }

}